package com.syni.mdd.yhd.common.all.controller.api.pay;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.IpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import com.jfinal.kit.StrKit;
import com.syni.mdd.yhd.common.all.config.pay.alipay.AlipayConfig;
import com.syni.mdd.yhd.common.all.config.pay.wxPay.WxPayBean;
import com.syni.mdd.yhd.common.all.config.pay.wxPay.WxPayBeanFactory;
import com.syni.mdd.yhd.common.all.constants.Constants;
import com.syni.mdd.yhd.common.all.constants.ResultCode;
import com.syni.mdd.yhd.common.all.constants.ResultMsg;
import com.syni.mdd.yhd.common.all.dto.requestDto.api.WeChatWithdrawalDto;
import com.syni.mdd.yhd.common.all.service.BmsDxOrderService;
import com.syni.mdd.yhd.common.all.service.DxshAppServiceOrderService;
import com.syni.mdd.yhd.common.all.service.pay.aiPay.AliPayService;
import com.syni.mdd.yhd.common.all.service.pay.aiPay.AlipayServiceImpl;
import com.syni.mdd.yhd.common.all.service.pay.wxPay.WxPayService;
import com.syni.mdd.yhd.common.all.service.record.ReTransferLogService;
import com.syni.mdd.yhd.common.all.utils.security.InterfaceSecurityUtil;
import com.syni.mdd.sjb.common.component.utils.common.utils.*;
import com.syni.mdd.sjb.common.component.utils.feign.dto.mddAll.apiPay.AliPayPrepayDto;
import com.syni.mdd.sjb.common.component.utils.feign.dto.mddAll.apiPay.PaySearchDto;
import com.syni.mdd.sjb.common.component.utils.feign.dto.mddAll.apiPay.WxPayPrepayDto;
import com.syni.mdd.sjb.common.component.utils.feign.service.mddAll.PayRestService;
import com.syni.mdd.sjb.common.component.utils.redis.utils.RedisTemplateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

;

/**
 * @className PayRestApi
 * @description TOO
 * @Author cfx
 * @DATE 2020/3/4 10:00
 * @VERSION 1.0
 **/
@RestController
@RequestMapping("/apiPay")
public class PayRestApi implements PayRestService {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    @Qualifier("aliPayConfig")
    AlipayConfig alipayConfig;

    @Autowired
    BmsDxOrderService bmsDxOrderService;

    @Autowired
    DxshAppServiceOrderService dxshAppServiceOrderService;


    @Autowired
    AliPayService aliPayService;

    @Autowired
    WxPayService wxPayService;

    @PostMapping("/refundLocalLifeOrder")
    public Map<String,Object> refundLocalLifeOrder(@RequestBody ParamsMap paramsMap){
        Integer orderId = paramsMap.getInteger("orderId");
        Map<String,Object> retMap;
        try {
            retMap = bmsDxOrderService.refundLocalLifeOrder(orderId);
        }catch (Exception e){
            retMap = ResultMapHelper.result(ResultCode.CODE_ORDER_REFUND_TOO_LOGN,"退款超时,请重试");
            logger.error("本地订单退款失败 ： " + e);
        }
        return retMap;
    }

    //@PostMapping("/aliPayTransfer")
    public Map<String,Object> aliPayTransfer(@RequestBody ParamsMap paramsMap){
        String AUTH = paramsMap.getString("AUTH");
        if(InterfaceSecurityUtil.checkInterfaceSec(AUTH)) {
            String total = paramsMap.getString("total");
            String bizNo = paramsMap.getString("bizNo");
            Double transMoney = Double.parseDouble(total);
            if (transMoney > 300d) {
                return ResultMapHelper.result(ResultCode.CODE_ERROR_100, "超过最大额度");
            }
            String userParams = paramsMap.getString("userParams");
            String[] decodedStr = MatchEncryptionUtils.decoded(userParams).split(":");
            if (decodedStr.length == 3) {
                String uid = decodedStr[1];
                if (aliPayService.transfersMoneyToPersonalAlipay(Double.parseDouble(total),uid,bizNo, ReTransferLogService.CHANNEL_MARKET_MACHINE)) {
                    return ResultMapHelper.success(new HashMap<>());
                }
            }
        }
        return ResultMapHelper.result(ResultCode.CODE_ERROR_100, ResultMsg.HAND_FAIL);
    }


    @PostMapping("/weChatWithdrawal")
    public Map<String,Object> weChatWithdrawal(@RequestBody WeChatWithdrawalDto weChatWithdrawalDto){
        String AUTH = weChatWithdrawalDto.getAuth();
        if(InterfaceSecurityUtil.checkInterfaceSec(AUTH)) {
            Map<String,Object> userParams = JSON.parseObject(MatchEncryptionUtils.decoded(weChatWithdrawalDto.getUserParams()));
            if(!(userParams.containsKey("total") && userParams.containsKey("userId"))){
                return ResultMapHelper.result(ResultCode.CODE_ERROR_100, ResultMsg.CODE_ERROR_PARAM_ERROR);
            }
            String total = userParams.get("total").toString();
            Integer userId = Integer.parseInt(userParams.get("userId").toString());
            String withdrawalNo = weChatWithdrawalDto.getWithdrawalNo();
            Double transMoney = Double.parseDouble(total);
            if (transMoney > 1000d) {
                return ResultMapHelper.result(ResultCode.CODE_ERROR_100, "超过当日提现最大额度");
            }
            Map<String,Object> callBackResultMap = wxPayService.transfersMoneyToPersonal(transMoney,userId,withdrawalNo,weChatWithdrawalDto.getHandleWay());
            return callBackResultMap;
        }
        return ResultMapHelper.result(ResultCode.CODE_ERROR_100, ResultMsg.CODE_ERROR_PARAM_ERROR);
    }

    /**
     * 发起支付宝支付
     * @return
     */
    /*@CheckParams(params = {"orderId","orderNo","notifyUrl"})
    @CheckParams(params = {"orderNo","payMoney","notifyUrl"})
    @PostMapping("/aliPayPrepay")
    @ResponseBody
    public Map<String,Object> aliPayPrepay(@RequestBody ParamsMap paramsMap) {
        Map<String, Object> resultMap = new HashMap<>();

        String orderNo = paramsMap.get("orderNo").toString();
        String payMoney = paramsMap.getString("payMoney");
        String notifyUrl = paramsMap.get("notifyUrl").toString();

        logger.info("下单动用的支付宝配置：" + JSON.toJSONString(alipayConfig));
        try {
            // 这个东西必备
            AlipayClient alipayClient = new DefaultAlipayClient(
                    alipayConfig.getServerUrl(),
                    alipayConfig.getAppid(),
                    alipayConfig.getPrivateKey(),
                    "json",
                    "UTF-8",
                    alipayConfig.getPublicKey(),
                    "RSA2");
            // 发起App支付请求
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            // 订单描述
            model.setBody(AlipayServiceImpl.PAY_DEFAULT_DESC);
            // 订单标题
            model.setSubject("订单号：" + orderNo);
            // 商户订单号 就是商户后台生成的订单号
            model.setOutTradeNo(orderNo);
            // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天 (屁股后面的字母一定要带，不然报错)
            model.setTimeoutExpress("30m");
            // 订单总金额 ，默认单位为元，精确到小数点后两位，取值范围[0.01,100000000]
            model.setTotalAmount(payMoney);
            // 销售产品码 不必填
            model.setProductCode("QUICK_MSECURITY_PAY");
            request.setBizModel(model);
            request.setNotifyUrl(notifyUrl);
            // 通过api的方法请求阿里接口获得反馈
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            if (response.isSuccess()) {
                System.out.println("支付调用成功");
            } else {
                System.out.println("支付调用失败");
            }
            //TODO 保存订单
            String result = response.getBody();
            resultMap.put("payCredent", result);
            System.out.println(result);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            return ResultMapHelper.result(ResultCode.CODE_PAY_ID_GET_FIAR, "支付凭证获取失败");
        }
        return ResultMapHelper.success(resultMap, ResultMsg.MSG_GET_SUCCESS);
    }*/

    @PostMapping("/aliPayPrepay")
    @ResponseBody
    public RpcResponseVo aliPayPrepay(@RequestBody AliPayPrepayDto aliPayPrepayDto) {
        String orderNo = aliPayPrepayDto.getOrderNo();
        String notifyUrl = aliPayPrepayDto.getNotifyUrl();
        String totalAmt = aliPayPrepayDto.getTotalAmt();
        AlipayClient alipayClient = aliPayService.getAlipayClient();
        try {
            // 发起App支付请求
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            // 订单描述
            model.setBody(AlipayServiceImpl.PAY_DEFAULT_DESC);
            // 订单标题
            model.setSubject("订单号：" + orderNo);
            // 商户订单号 就是商户后台生成的订单号
            model.setOutTradeNo(orderNo);
            // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天 (屁股后面的字母一定要带，不然报错)
            model.setTimeoutExpress("30m");
            // 订单总金额 ，默认单位为元，精确到小数点后两位，取值范围[0.01,100000000]
            model.setTotalAmount(totalAmt);
            // 销售产品码 不必填
            model.setProductCode("QUICK_MSECURITY_PAY");
            request.setBizModel(model);
            request.setNotifyUrl(alipayConfig.getMicroServiceCallBackUrl());
            // 通过api的方法请求阿里接口获得反馈
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            if (response.isSuccess()) {
                //存入redis
                RedisTemplateUtils.getRedisTemplate().opsForValue().set(Constants.REDIS_KEY_MICOS_PAY + orderNo,notifyUrl);
                String result = response.getBody();
                aliPayPrepayDto.setPayCredent(result);
                return RpcResponseVo.success(aliPayPrepayDto,ResultMsg.MSG_GET_SUCCESS);
            }
            //TODO 保存订单
        } catch (Exception e) {
            logger.error("支付凭证获取失败：",e);
        }
        return RpcResponseVo.result(ResultCode.CODE_ERROR_100, "支付凭证获取失败");
    }


    @PostMapping("/wxPayPrepay")
    public RpcResponseVo wxPayPrepay(@RequestBody WxPayPrepayDto wxPayPrepayDto) {
        if(!StringUtils.isNotBlank(wxPayPrepayDto.getNotifyUrl())){
            return RpcResponseVo.result(ResultCode.CODE_ERROR_03,ResultMsg.CODE_ERROR_PARAM_ERROR);
        }
        HttpServletRequest request = RequestParamUtils.getRequest();
        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        WxPayBean wxPayApiConfig = wxPayService.getApiConfigByChannel(WxPayBeanFactory.APP_MDD_DATA_BANK_CHANNEL);
        String orderNo = wxPayPrepayDto.getOrderNo();
        String totalFee = wxPayPrepayDto.getTotalAmt();
        if(StringUtils.isBlank(wxPayPrepayDto.getBody())){
            wxPayPrepayDto.setBody("微信支付");
        }
        if(StringUtils.isBlank(wxPayPrepayDto.getAttach())){
            wxPayPrepayDto.setAttach("微信支付");
        }
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(wxPayPrepayDto.getBody())
                .attach(wxPayPrepayDto.getAttach())
                .out_trade_no(orderNo)
                .total_fee(totalFee)
                .spbill_create_ip(ip)
                .notify_url(wxPayApiConfig.getAppPayServiceCallBackUrl())
                .trade_type(TradeType.APP.getTradeType())
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, params);

        logger.info("origin xml: " + xmlResult);
        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
        logger.info("de xml : " + JSON.toJSONString(result));
        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        logger.info("returnMsg : " + returnMsg);
        if (!WxPayKit.codeIsOk(returnCode)) {
            RpcResponseVo.result(ResultCode.CODE_ERROR_100, "支付凭证获取失败");
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            RpcResponseVo.result(ResultCode.CODE_ERROR_100, "支付凭证获取失败");
        }
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");

        Map<String, String> packageParams = WxPayKit.appPrepayIdCreateSign(wxPayApiConfig.getAppId(), wxPayApiConfig.getMchId(), prepayId,
                wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String jsonStr = JSON.toJSONString(packageParams);
        logger.info("返回apk的参数:" + jsonStr);
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.putAll(JSON.parseObject(jsonStr));
        RedisTemplateUtils.getRedisTemplate().opsForValue().set(Constants.REDIS_KEY_MICOS_PAY + orderNo,wxPayPrepayDto.getNotifyUrl());
        return RpcResponseVo.success(resultMap, ResultMsg.MSG_GET_SUCCESS);
    }

    @PostMapping("/paySearch")
    public Map<String,Object> paySearch(@RequestBody PaySearchDto paySearchDto) {
        Map<String,Object> returnMap = new HashMap<>();
        //无法确定
        returnMap.put("isPay",Constants.COMMON_NOKNOW_INT);
        Map<String,Object> resultMap = new HashMap<>();
        if(paySearchDto.getSearchWay() == PaySearchDto.SEARCH_WAY_ALI){
            resultMap = aliPayService.appOrderQuery(paySearchDto.getOutTradeNo(),aliPayService.getAlipayClient());
        } else if(paySearchDto.getSearchWay() == PaySearchDto.SEARCH_WAY_WX){
            resultMap = wxPayService.orderQuery(paySearchDto.getOutTradeNo(),WxPayBeanFactory.APP_MDD_DATA_BANK_CHANNEL);
        }
        if(resultMap.containsKey("isPay")){
            Integer isPay = Integer.parseInt(resultMap.get("isPay").toString());
            if(isPay == Constants.COMMON_FLAG_TRUE_INT){
                returnMap.put("isPay",Constants.COMMON_FLAG_TRUE_INT);
                if(resultMap.containsKey("tradeNo")){
                    returnMap.put("thirdPartyPayno",resultMap.get("tradeNo").toString());
                }
                if(resultMap.containsKey("totalAmount")){
                    returnMap.put("totalAmount",resultMap.get("totalAmount").toString());
                }
            } else if(isPay == Constants.COMMON_FLAG_FALSE_INT ){
                returnMap.put("isPay",Constants.COMMON_FLAG_FALSE_INT);
            }
        }
        return ResultMapHelper.success(returnMap, ResultMsg.MSG_GET_SUCCESS);
    }
}
